Skip to content

Handle composite foreign keys in positioning scope changes#62

Merged
brendon merged 12 commits intomainfrom
copilot/fix-positioning-bug
Mar 28, 2026
Merged

Handle composite foreign keys in positioning scope changes#62
brendon merged 12 commits intomainfrom
copilot/fix-positioning-bug

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 27, 2026

Since we now only test against Rails 7.2 and greater, this PR removes all version-conditional skips and guards across the test suite, and adds full support for composite foreign key scope changes.

Changes Made

  • Removed if ActiveRecord.version >= Gem::Version.new("7.2.0") guard from test/support/active_record.rb — always create the composite_foreign_key_items table
  • Removed if ActiveRecord.version >= Gem::Version.new("7.2.0") guard from test/models/composite_foreign_key_item.rb — always define the class
  • Removed if ActiveRecord.version >= Gem::Version.new("7.2.0") guard from test/models/composite_primary_key_item.rb — always define the has_many
  • Removed skip lines from test/test_positioning.rb (3 × 7.2.0 skips, 1 × 7.1.0 skip)
  • Changed positioning_columns[column][:scope_columns] << reflection.foreign_key to positioning_columns[column][:scope_columns].concat Array(reflection.foreign_key) in lib/positioning.rb so composite FK columns are stored flat (e.g. ["cpki_item_id", "cpki_account_id"] instead of [["cpki_item_id", "cpki_account_id"]])
  • Changed destroyed_via_positioning_scope? in lib/positioning/mechanisms.rb to use Array(@positioned.destroyed_by_association.foreign_key).include?(scope_column) so it correctly handles both string and array foreign keys
  • Renamed belongs_to :composite_primary_key_item to belongs_to :list (with class_name: "CompositePrimaryKeyItem") on CompositeForeignKeyItem so the model fits the TestPositioning abstract nomenclature where scope-change tests use update list: @second_list
  • Added -> { order(:position) } to has_many :composite_foreign_key_items on CompositePrimaryKeyItem
  • TestCompositeForeignKeyPositioning now extends TestPositioning and inherits all positioning tests including scope-change tests — no no-op'd overrides

Testing

  • 225 runs, 3217 assertions, 0 failures, 0 errors, 0 skips
  • Linter passes
  • CodeQL — no alerts

💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

In Rails 7.2+, destroyed_by_association.foreign_key returns an Array
for composite foreign keys. The previous code compared the Array
directly against individual scope column strings, which always
returned false. This caused unnecessary position contraction when
destroying a parent record through an association with composite keys.

Also fix scope_columns setup in positioned() to properly flatten
composite foreign keys into individual column entries.

Agent-Logs-Url: https://github.com/brendon/positioning/sessions/18f96f84-12eb-4a58-ba20-4eaea20fe690

Co-authored-by: brendon <81871+brendon@users.noreply.github.com>
@brendon
Copy link
Copy Markdown
Owner

brendon commented Mar 27, 2026

@copilot, Why is vendor/bundle/ruby/3.2.0 in the PR?

Copy link
Copy Markdown

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 27, 2026

@copilot, Why is vendor/bundle/ruby/3.2.0 in the PR?

Sorry about that — vendor/bundle was accidentally committed when running bundle install locally during development. Removed in 629a239. The PR now only contains the 3 intended files.

Copilot AI requested a review from brendon March 27, 2026 01:34
Copilot AI and others added 2 commits March 27, 2026 09:53
…model-based tests

- Revert destroyed_via_positioning_scope? to brendon's && style
- Remove .map(&:to_s) and .to_s calls (foreign keys are already strings)
- Use << operator via Array().each for scope_columns in positioned
- Replace mocked composite FK tests with proper model-based integration tests
- Add CompositeKeyList/CompositeKeyListItem models for Rails 7.2+ testing

Agent-Logs-Url: https://github.com/brendon/positioning/sessions/9ada62a9-2611-4113-9f17-e6c8f2ac9738

Co-authored-by: brendon <81871+brendon@users.noreply.github.com>
- Use concat instead of .each { |fk| << fk } in positioning.rb as brendon requested
- Remove CompositeKeyList/CompositeKeyListItem models created from scratch
- Reuse existing CompositePrimaryKeyItem (which has composite PK) as parent
- Create minimal CompositeForeignKeyItem child with composite FK to it

Agent-Logs-Url: https://github.com/brendon/positioning/sessions/fd37d2c2-d391-4065-94bd-c2f48fe26b0a

Co-authored-by: brendon <81871+brendon@users.noreply.github.com>
@brendon brendon marked this pull request as ready for review March 27, 2026 21:42
Copilot AI changed the title Handle composite foreign keys in destroyed_via_positioning_scope? Remove Rails version skips and guards (now targeting Rails 7.2+) Mar 28, 2026
Copilot AI requested a review from brendon March 28, 2026 00:19
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 28, 2026

@copilot, Why is vendor/bundle/ruby/3.2.0 in the PR?

It was accidentally committed during bundle install and removed in 629a239. The PR no longer contains vendor/bundle.

Copilot AI changed the title Remove Rails version skips and guards (now targeting Rails 7.2+) Handle composite foreign keys in positioning scope changes Mar 28, 2026
Copilot AI requested a review from brendon March 28, 2026 02:43

if reflection&.belongs_to?
positioning_columns[column][:scope_columns].concat Array(reflection.foreign_key)
positioning_columns[column][:scope_columns] << reflection.foreign_key
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this changed back too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restored in 6f04242 — now uses concat Array(reflection.foreign_key) to flatten composite FK columns into individual entries.

…).include? in destroyed_via_positioning_scope?, remove unnecessary .flatten

Agent-Logs-Url: https://github.com/brendon/positioning/sessions/8234fc70-91d7-47de-8d93-cc94bffa2f8d

Co-authored-by: brendon <81871+brendon@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 28, 2026

@copilot, Why is vendor/bundle/ruby/3.2.0 in the PR?

It was accidentally committed during bundle install and removed in 629a239. The PR no longer contains vendor/bundle.

Copilot AI requested a review from brendon March 28, 2026 04:29
…n: destroy child first, refute, then destroy parent, assert

Agent-Logs-Url: https://github.com/brendon/positioning/sessions/7411e026-7446-4bbb-bfca-9e1f8f018683

Co-authored-by: brendon <81871+brendon@users.noreply.github.com>
Copilot AI requested a review from brendon March 28, 2026 05:47
Remove RAILS_VERSION-based conditional in Gemfile and unconditionally use gem 'sqlite3', '~> 2.9.0' when ENV['DB'] == 'sqlite'. This removes the older ~>1.7.3 fallback and simplifies sqlite dependency/version handling.
@brendon brendon merged commit 2c8d519 into main Mar 28, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants